using FileManager.Models;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;

namespace FileManager.Services
{
    /// <summary>
    /// 重复文件查找器服务类
    /// 提供查找、统计和删除重复文件的功能
    /// </summary>
    public class DuplicateFileFinder
    {
        private readonly AppDbContext _dbContext;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="dbContext">数据库上下文</param>
        public DuplicateFileFinder(AppDbContext dbContext)
        {
            _dbContext = dbContext;
        }

        /// <summary>
        /// 查找所有重复文件
        /// </summary>
        /// <returns>重复文件组列表</returns>
        public async Task<List<DuplicateFileGroup>> FindDuplicateFilesAsync()
        {
            var result = new List<DuplicateFileGroup>();

            try
            {
                // 获取数据库中的文件总数，用于快速检查
                var totalFiles = await _dbContext.Files.CountAsync();
                if (totalFiles < 2)
                {
                    return result; // 文件数量不足，无法形成重复文件
                }

                // 查找具有相同哈希值的文件，排除哈希计算错误的文件
                var duplicateHashes = await _dbContext.Files
                    .Where(f => !string.IsNullOrEmpty(f.HashValue) && f.HashValue != "hash_error")
                    .GroupBy(f => f.HashValue)
                    .Where(g => g.Count() > 1)
                    .Select(g => g.Key)
                    .ToListAsync();

                foreach (var hash in duplicateHashes)
                {
                    var files = await _dbContext.Files
                        .Where(f => f.HashValue == hash)
                        .ToListAsync();

                    // 按文件大小分组，相同大小的文件才可能是重复的
                    var sizeGroups = files.GroupBy(f => f.FileSize);

                    foreach (var sizeGroup in sizeGroups)
                    {
                        if (sizeGroup.Count() > 1)
                        {
                            var group = new DuplicateFileGroup
                            {
                                HashValue = hash,
                                FileSize = sizeGroup.Key,
                                Files = sizeGroup.ToList()
                            };

                            result.Add(group);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"查找重复文件时出错: {ex.Message}");
            }

            return result;
        }

        /// <summary>
        /// 删除重复文件组中的重复文件，保留指定文件
        /// </summary>
        /// <param name="group">重复文件组</param>
        /// <param name="fileToKeep">要保留的文件</param>
        public async Task DeleteDuplicateFilesAsync(DuplicateFileGroup group, FileItem fileToKeep)
        {
            if (group == null || fileToKeep == null)
            {
                Console.WriteLine("无效的重复文件组或要保留的文件");
                return;
            }

            if (!group.Files.Any(f => f.Id == fileToKeep.Id))
            {
                Console.WriteLine("要保留的文件不在指定的重复文件组中");
                return;
            }

            try
            {
                int filesToDeleteCount = group.Files.Count - 1;
                if (filesToDeleteCount <= 0)
                {
                    return; // 没有需要删除的文件
                }

                for (int i = group.Files.Count - 1; i >= 0; i--)
                {
                    var file = group.Files[i];
                    if (file.Id != fileToKeep.Id)
                    {
                        try
                        {
                            // 检查文件是否存在
                            if (File.Exists(file.FilePath))
                            {
                                // 删除物理文件
                                File.Delete(file.FilePath);
                                Console.WriteLine($"已删除物理文件: {file.FilePath}");
                            }

                            // 从数据库中删除
                            _dbContext.Files.Remove(file);
                            group.Files.RemoveAt(i);
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine($"删除文件 {file.FilePath} 时出错: {ex.Message}");
                        }
                    }
                }

                await _dbContext.SaveChangesAsync();
            }
            catch { }
        }

        /// <summary>
        /// 获取重复文件的数量
        /// </summary>
        /// <returns>重复文件的数量</returns>
        public async Task<int> GetDuplicateFilesCountAsync()
        {
            try
            {
                var duplicateGroups = await FindDuplicateFilesAsync();
                return duplicateGroups.Sum(g => g.Files.Count - 1); // 每组中除了保留一个文件外，其余都是重复的
            }
            catch (Exception ex)
            {
                Console.WriteLine($"统计重复文件数量时出错: {ex.Message}");
                return 0;
            }
        }

        /// <summary>
        /// 获取重复文件占用的总空间
        /// </summary>
        /// <returns>重复文件占用的总空间(字节)</returns>
        public async Task<long> GetDuplicateFilesSizeAsync()
        {
            try
            {
                var duplicateGroups = await FindDuplicateFilesAsync();
                return duplicateGroups.Sum(g => g.FileSize * (g.Files.Count - 1)); // 每组中除了保留一个文件外，其余都是重复的
            }
            catch (Exception ex)
            {
                Console.WriteLine($"计算重复文件大小时出错: {ex.Message}");
                return 0;
            }
        }
    }
}
